package com.derbysoft.ota.infrastructure.guice;


import java.util.Map.Entry;

import org.springframework.ws.transport.http.MessageDispatcherServlet;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.ota.application.service.CancelService;
import com.derbysoft.ota.application.service.HotelAvailService;
import com.derbysoft.ota.application.service.HotelCodeRetriever;
import com.derbysoft.ota.application.service.HotelResService;
import com.derbysoft.ota.application.service.HotelSearchService;
import com.derbysoft.ota.application.service.impl.CancelServiceImpl;
import com.derbysoft.ota.application.service.impl.HotelAvailServiceImpl;
import com.derbysoft.ota.application.service.impl.HotelResServiceImpl;
import com.derbysoft.ota.application.service.impl.HotelSearchServiceImpl;
import com.derbysoft.ota.application.service.impl.TpaExtensionHotelCodeRetriever;
import com.derbysoft.ota.application.translator.rq.AddressRQTranslator;
import com.derbysoft.ota.application.translator.rq.AgeQualifyingTypeTranslator;
import com.derbysoft.ota.application.translator.rq.CancelRQTranslator;
import com.derbysoft.ota.application.translator.rq.CardCodeTranslator;
import com.derbysoft.ota.application.translator.rq.CardTypeTranslator;
import com.derbysoft.ota.application.translator.rq.GuaranteeRQTranslator;
import com.derbysoft.ota.application.translator.rq.GuaranteeTypeRQTranslator;
import com.derbysoft.ota.application.translator.rq.GuestTranslator;
import com.derbysoft.ota.application.translator.rq.HotelAvailRQTranslator;
import com.derbysoft.ota.application.translator.rq.HotelResRequestTypeTranslator;
import com.derbysoft.ota.application.translator.rq.HotelReservationRQTranslator;
import com.derbysoft.ota.application.translator.rq.HotelSearchCriteriaTranslator;
import com.derbysoft.ota.application.translator.rq.HotelSearchRQTranslator;
import com.derbysoft.ota.application.translator.rq.LanguageTypeTranslator;
import com.derbysoft.ota.application.translator.rq.RequestHeaderTranslator;
import com.derbysoft.ota.application.translator.rq.RoomStayRQTranslator;
import com.derbysoft.ota.application.translator.rq.TelephoneTranslator;
import com.derbysoft.ota.application.translator.rs.AvailRoomRateTranslator;
import com.derbysoft.ota.application.translator.rs.CancelPenaltiesTranslator;
import com.derbysoft.ota.application.translator.rs.CancelRSTranslator;
import com.derbysoft.ota.application.translator.rs.HotelAvailRSCriteriaTranslator;
import com.derbysoft.ota.application.translator.rs.HotelAvailRSSource;
import com.derbysoft.ota.application.translator.rs.HotelAvailRSTranslator;
import com.derbysoft.ota.application.translator.rs.HotelPropertyTranslator;
import com.derbysoft.ota.application.translator.rs.HotelResResponseTypeSource;
import com.derbysoft.ota.application.translator.rs.HotelReservationRSTranslator;
import com.derbysoft.ota.application.translator.rs.HotelReservationTypeRSTranslator;
import com.derbysoft.ota.application.translator.rs.HotelSearchRSTranslator;
import com.derbysoft.ota.application.translator.rs.RateTranslator;
import com.derbysoft.ota.application.translator.rs.ResGlobalInfoTranslator;
import com.derbysoft.ota.application.translator.rs.ResRoomRateTranslator;
import com.derbysoft.ota.application.translator.rs.RoomStayRSSource;
import com.derbysoft.ota.application.translator.rs.RoomStayRSTranslator;
import com.derbysoft.ota.application.translator.rs.TotalTranslator;
import com.derbysoft.ota.application.translator.rs.TransactionStatusTypeTranslator;
import com.derbysoft.ota.domain.city.CityCodeService;
import com.derbysoft.ota.domain.city.CityCodeServiceImpl;
import com.derbysoft.ota.interfaces.protocol._2009a.CancelPenaltiesType;
import com.derbysoft.ota.interfaces.protocol._2009a.CustomerType;
import com.derbysoft.ota.interfaces.protocol._2009a.DateTimeSpanType;
import com.derbysoft.ota.interfaces.protocol._2009a.GuaranteeType;
import com.derbysoft.ota.interfaces.protocol._2009a.HotelResRequestType;
import com.derbysoft.ota.interfaces.protocol._2009a.HotelResResponseType;
import com.derbysoft.ota.interfaces.protocol._2009a.HotelReservationType;
import com.derbysoft.ota.interfaces.protocol._2009a.OTACancelRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.OTACancelRS;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelAvailRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelAvailRS;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelSearchRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.POSType;
import com.derbysoft.ota.interfaces.protocol._2009a.PropertiesType;
import com.derbysoft.ota.interfaces.protocol._2009a.ResGlobalInfoType;
import com.derbysoft.ota.interfaces.protocol._2009a.TotalType;
import com.derbysoft.ota.interfaces.protocol._2009a.TransactionStatusType;
import com.derbysoft.ota.interfaces.protocol._2009a.AvailRequestSegmentsType.AvailRequestSegment;
import com.derbysoft.ota.interfaces.protocol._2009a.CustomerType.Address;
import com.derbysoft.ota.interfaces.protocol._2009a.CustomerType.Telephone;
import com.derbysoft.ota.interfaces.protocol._2009a.GuaranteeType.GuaranteeTypeEnum;
import com.derbysoft.ota.interfaces.protocol._2009a.HotelSearchCriteriaType.Criterion;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelAvailRS.Criteria;
import com.derbysoft.ota.interfaces.protocol._2009a.PropertiesType.Property;
import com.derbysoft.ota.interfaces.protocol._2009a.RateType.Rate;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStayType.RoomRates.RoomRate;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStaysType.RoomStay;
import com.derbysoft.remote.dhis.DHisIATAAirport2CityWebServiceFactory;
import com.derbysoft.remote.dhis.httpinvoker.HttpInvokerDHisIATAAirport2CityWebServiceFactory;
import com.derbysoft.remote.dswitch.core.RequestHeader;
import com.derbysoft.remote.dswitch.generic.constants.AgeQualifyingType;
import com.derbysoft.remote.dswitch.generic.constants.CardCode;
import com.derbysoft.remote.dswitch.generic.constants.CardType;
import com.derbysoft.remote.dswitch.generic.dto.CustomerDTO;
import com.derbysoft.remote.dswitch.generic.dto.GuaranteeDTO;
import com.derbysoft.remote.dswitch.generic.dto.TelephoneDTO;
import com.derbysoft.remote.dswitch.hotel.dswitch.DSwitch4HotelBuyerWebServiceFactory;
import com.derbysoft.remote.dswitch.hotel.dswitch.httpinvoker.HttpInvokerDSwitch4HotelBuyerWebServiceFactory;
import com.derbysoft.remote.dswitch.hotel.dto.AvailRoomStayDTO;
import com.derbysoft.remote.dswitch.hotel.dto.CancelPolicyDTO;
import com.derbysoft.remote.dswitch.hotel.dto.CancelRQ;
import com.derbysoft.remote.dswitch.hotel.dto.CancelRS;
import com.derbysoft.remote.dswitch.hotel.dto.HotelMultiProviderAvailRQ;
import com.derbysoft.remote.dswitch.hotel.dto.HotelReservationDTO;
import com.derbysoft.remote.dswitch.hotel.dto.HotelReservationRQ;
import com.derbysoft.remote.dswitch.hotel.dto.HotelReservationRS;
import com.derbysoft.remote.dswitch.hotel.dto.HotelSearchCriteriaDTO;
import com.derbysoft.remote.dswitch.hotel.dto.HotelSearchPropertyDTO;
import com.derbysoft.remote.dswitch.hotel.dto.HotelSearchRQ;
import com.derbysoft.remote.dswitch.hotel.dto.HotelSearchRS;
import com.derbysoft.remote.dswitch.hotel.dto.RateDTO;
import com.derbysoft.remote.dswitch.hotel.dto.ReservationRoomStayDTO;
import com.derbysoft.remote.dswitch.hotel.dto.TotalDTO;
import com.derbysoft.remote.share.LanguageType;
import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
import com.google.inject.servlet.ServletModule;

public abstract class Modules {

	public static ServletModule ws() {
		return new ServletModule() {
			protected void configureServlets() {
				Key<MessageDispatcherServlet> springwsKey = Key.get(MessageDispatcherServlet.class, Names.named("spring-ws"));
				serve("/soap/*").with(springwsKey);
				bind(springwsKey).toProvider(springwsServletProvider()).in(Scopes.SINGLETON);
			}
		};
	}
	
	private static Provider<MessageDispatcherServlet> springwsServletProvider() {
		return new Provider<MessageDispatcherServlet>() {
			public MessageDispatcherServlet get() {
				MessageDispatcherServlet servlet = new MessageDispatcherServlet();
				servlet.setTransformWsdlLocations(true);
				servlet.setContextConfigLocation("classpath:spring/injector.xml, WEB-INF/spring-ws-servlet.xml");
                return servlet;
			}
		};
	}

    public static Module domain() {
        return new AbstractModule() {
            protected void configure() {
            	install(translator());
            	install(service());
            }
        };
    }
    
	private static Module translator() {
		return new AbstractModule() {
			protected void configure() {
				bind(new TypeLiteral<Translator<OTAHotelSearchRQ, HotelSearchRQ>>() {}).to(HotelSearchRQTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Entry<String, Criterion>, HotelSearchCriteriaDTO>>() {}).to(HotelSearchCriteriaTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Entry<OTAHotelSearchRQ, HotelSearchRS>, PropertiesType>>() {}).to(HotelSearchRSTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Entry<OTAHotelSearchRQ, HotelSearchPropertyDTO>, Property>>() {}).to(HotelPropertyTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<String, LanguageType>>() {}).to(LanguageTypeTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<POSType, RequestHeader>>() {}).to(RequestHeaderTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<HotelResRequestType, HotelReservationRQ>>() {}).to(HotelReservationRQTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<HotelResRequestType, HotelReservationDTO>>() {}).to(HotelResRequestTypeTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<GuaranteeType, GuaranteeDTO>>() {}).to(GuaranteeRQTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<RoomStay, ReservationRoomStayDTO>>() {}).to(RoomStayRQTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<CustomerType, CustomerDTO>>() {}).to(GuestTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Address, String>>() {}).to(AddressRQTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Telephone, TelephoneDTO>>() {}).to(TelephoneTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<String, CardCode>>() {}).to(CardCodeTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<HotelResResponseTypeSource, HotelResResponseType>>() {}).to(HotelReservationRSTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<com.derbysoft.remote.dswitch.generic.constants.TransactionStatusType, TransactionStatusType>>() {}).to(TransactionStatusTypeTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Entry<HotelReservationRS, HotelReservationType>, HotelReservationType>>() {}).to(HotelReservationTypeRSTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Entry<HotelReservationRS, ResGlobalInfoType>, ResGlobalInfoType>>() {}).to(ResGlobalInfoTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<RoomStayRSSource, RoomStay>>() {}).to(RoomStayRSTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<ReservationRoomStayDTO, RoomRate>>() {}).to(ResRoomRateTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<TotalDTO, TotalType>>() {}).to(TotalTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<CancelPolicyDTO, CancelPenaltiesType>>() {}).to(CancelPenaltiesTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<OTACancelRQ, CancelRQ>>() {}).to(CancelRQTranslator.class).in(Scopes.SINGLETON);
                bind(new TypeLiteral<Translator<Entry<CancelRS, OTACancelRS>, OTACancelRS>>() {}).to(CancelRSTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<String, CardType>>() {}).to(CardTypeTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<RateDTO, Rate>>() {}).to(RateTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<Entry<AvailRoomStayDTO, DateTimeSpanType>, RoomRate>>() {}).to(AvailRoomRateTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<HotelAvailRSSource, OTAHotelAvailRS>>() {}).to(HotelAvailRSTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<String, AgeQualifyingType>>() {}).to(AgeQualifyingTypeTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<OTAHotelAvailRQ, HotelMultiProviderAvailRQ>>() {}).to(HotelAvailRQTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<GuaranteeTypeEnum, com.derbysoft.remote.dswitch.hotel.constants.GuaranteeType>>() {}).to(GuaranteeTypeRQTranslator.class).in(Scopes.SINGLETON);
				bind(new TypeLiteral<Translator<AvailRequestSegment, Criteria>>() {}).to(HotelAvailRSCriteriaTranslator.class).in(Scopes.SINGLETON);
			}
		};
	}
	
	private static Module service() {
		return new AbstractModule() {
			protected void configure() {
                bind(HotelSearchService.class).to(HotelSearchServiceImpl.class).in(Scopes.SINGLETON);
                bind(DSwitch4HotelBuyerWebServiceFactory.class).toInstance(new HttpInvokerDSwitch4HotelBuyerWebServiceFactory(Environments.get().getProperty("dswitch2.uri")));
                bind(CityCodeService.class).to(CityCodeServiceImpl.class).in(Scopes.SINGLETON);
                bind(HotelAvailService.class).to(HotelAvailServiceImpl.class).in(Scopes.SINGLETON);
                bind(HotelResService.class).to(HotelResServiceImpl.class).in(Scopes.SINGLETON);
                bind(CancelService.class).to(CancelServiceImpl.class).in(Scopes.SINGLETON);
                //TODO consider store hotel code on reservation time.
                bind(HotelCodeRetriever.class).to(TpaExtensionHotelCodeRetriever.class).in(Scopes.SINGLETON);
				bind(DHisIATAAirport2CityWebServiceFactory.class).toInstance(new HttpInvokerDHisIATAAirport2CityWebServiceFactory(Environments.get().getProperty("dhis.uri")));
			}
		};
	}
	
}
